package cs.rsa.ts14.kilo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cs.rsa.ts14.framework.LineType;
import cs.rsa.ts14.framework.LineTypeClassifierStrategy;

public class StandardLineTypeClassifierStrategy implements
		LineTypeClassifierStrategy {

	private String[] weekDays = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
			"Sun" };
	private String[] transportMode = { "Bi", "Ca", "Pu", "Tr", "No", "Ho" };

	private boolean atLeastOneAssignmentLineFound=false;

	private boolean noMoreAssignmentLinesAllowed = false;
	private LineType previousType;
	
	private int emptyLineCounter = 0;

	@Override
	public LineType classify(String line) 
	{	
		if(emptyLineCounter >= 2 || previousType ==LineType.INVALID_SEQUENCE )
		{
			previousType =LineType.INVALID_SEQUENCE;
			return LineType.INVALID_SEQUENCE;
		}
		if (isEmptyLine(line))
		{
			emptyLineCounter++;
			previousType = LineType.EMPTY_LINE;
			return LineType.EMPTY_LINE;
		}
		emptyLineCounter = 0;	
		
		
		if (line.charAt(0) == '#')
		{
			previousType = LineType.COMMENT_LINE;
			return LineType.COMMENT_LINE;
		}
		if (isAssignmentLine(line)){
			if (noMoreAssignmentLinesAllowed)
				return LineType.INVALID_SEQUENCE;
			atLeastOneAssignmentLineFound = true;
			previousType = LineType.ASSIGNMENT_LINE;
			return LineType.ASSIGNMENT_LINE;
		}
		
		String[] items = line.split("(\\s|\\t)+");		
		  
		if(atLeastOneAssignmentLineFound)
		{
			if (isWeekLine(line)){
				noMoreAssignmentLinesAllowed = true;
				  previousType = LineType.WEEK_SPECIFICATION;
				  return LineType.WEEK_SPECIFICATION;
			}
			if(items.length >= 2 )
			{
		    if(ArrayContainValue(weekDays, items[0]) && ArrayContainValue(transportMode, items[1]))
		    {
		    	if(previousType == LineType.WEEK_SPECIFICATION ||previousType == LineType.EMPTY_LINE || previousType ==  LineType.WEEKDAY_SPECIFICATION ||previousType == LineType.COMMENT_LINE)
		    	{
					noMoreAssignmentLinesAllowed = true;
		    	  previousType = LineType.WEEKDAY_SPECIFICATION;
		    	  return LineType.WEEKDAY_SPECIFICATION;
		    	}
		    	else
		    	{
		    		previousType =LineType.INVALID_SEQUENCE;
					return LineType.INVALID_SEQUENCE;
		    	}
		    }
		  }		  
		  
		  if (isWorkSpecificationLine(line)){
			  if(previousType == LineType.WEEKDAY_SPECIFICATION ||previousType == LineType.EMPTY_LINE ||previousType == LineType.WORK_SPECIFICATION || previousType == LineType.COMMENT_LINE){
					noMoreAssignmentLinesAllowed = true;
					  previousType = LineType.WORK_SPECIFICATION;
					  return LineType.WORK_SPECIFICATION;
		    	}
		    	else{
		    		previousType =LineType.INVALID_SEQUENCE;
					return LineType.INVALID_SEQUENCE;
		    	}
		  }
		}
		else
		{
			 previousType =LineType.INVALID_SEQUENCE;
			return LineType.INVALID_SEQUENCE;
		}
		  
		 previousType =LineType.INVALID_LINE;
		return LineType.INVALID_LINE;
	}
	private boolean isEmptyLine(String line){
		
		if (line == null)
			return true;
	    Pattern p = Pattern.compile("^(\\s|\\t)*$",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
	    Matcher m = p.matcher(line);
	    return m.find();
	}
	private boolean isWorkSpecificationLine(String line){
		// eks. "	censor	-		7.5";	
		String tabOrWs = "(\\s|\\t)+";
	    String decimal="(([+-]?\\d*\\.\\d)|(\\d+))";	// a float/double value with 1 decimal

	    Pattern p = Pattern.compile("^"+tabOrWs+"[a-zA-Z]+"+tabOrWs+"([a-zA-Z]+|-)+"+tabOrWs+decimal+"("+tabOrWs+".)*$",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
	    Matcher m = p.matcher(line);
	    boolean result =  m.find();
	    return result;
	}
	private boolean isAssignmentLine(String line){
		String txt=line;
		String tabOrWs = "(\\s|\\t)+";
	    String re1="((?:[a-z][a-z]+))";	// Word 1
	    String re2=tabOrWs;
	    String re3="(=)";	// '=' char
	    String re4=tabOrWs;
	    String re5="(([+-]?\\d*\\.\\d)|(\\d+))";	// a float/double value with 1 decimal

	    Pattern p = Pattern.compile("^"+re1+re2+re3+re4+re5+"$",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
	    Matcher m = p.matcher(txt);
	    return m.find();
	}
	public boolean isWeekLine(String line){
		//"Week 1 : 3 : 0";
		String tabOrWs = "(\\s|\\t)+";
	    Pattern p = Pattern.compile("^Week"+tabOrWs+"(([1-9])|([1-4][0-9])|(5[0-3]))"+tabOrWs+":"+tabOrWs+"[0-5]"+tabOrWs+":"+tabOrWs+"[0-5]$",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
//	    System.out.print(p.toString());
	    Matcher m = p.matcher(line);
	    return m.find();
	}
	private boolean tryParseInt(String value) {
		try {
			Integer.parseInt(value);
			return true;
		} catch (NumberFormatException nfe) {
			return false;
		}
	}

	private boolean tryParseDouble(String value)
	{
		try 
		{
			Double.parseDouble(value);
			return true;
		} 
		catch (NumberFormatException nfe) 
		{
			return false;
		}
	}

	private boolean ArrayContainValue(String[] array, String value) {
		if (array.length == 0 || value.isEmpty())
			return false;

		for (int i = 0; i < array.length; i++) {
			if (array[i].equals(value))
				return true;
		}
		return false;
	}

	@Override
	public String lastError() {
		// TODO Auto-generated method stub
		return null;
	}

}
